#ifndef REAC_HPP
#define REAC_HPP

#include <vector>
#include <unordered_map>
#include "log.hpp"
#include "Epoll.hpp"
#include "Connect.hpp"
using namespace LOG;

class Reactor
{
public:
    Reactor():
    _isrunning(false)
    {}

    ~Reactor() {}

    void AddConnect(int sockfd,class Addr addr,int type)
    {   
        Connect* conn = new Connect(sockfd,addr);
        conn->_type = type;
        conn->LinkR(this);
        if(type == LISTENSOCKFD)
        {
            conn->_event.events = EPOLLIN | EPOLLERR;
            conn->RegistListenHandlers(_listen_sockfd_read,nullptr,nullptr);
        }
        else
        {
            conn->_event.events = EPOLLOUT | EPOLLERR | EPOLLHUP;
            conn->RegistNormalHandlers(_normal_sockfd_read,_normal_sockfd_write,_except);
        }
        epoll.Add(conn->Sockfd(),conn->Event());
        _ConnPool[sockfd] = conn;
    }
    void SetOnConnect(handlers handler)
    {
        _listen_sockfd_read = handler;
    }
    void SetNormalHandlers(handlers read,handlers write,handlers except)
    {
        _normal_sockfd_read = read;
        _normal_sockfd_write = write;
        _except = except;
    }
    void LoopOnce()
    {
        int timeout = 5;
        int n = epoll.Wait(revs,timeout);
        if(n > 0)
        {
            PrintDebug();
            for(int i = 0;i < n;i++)
            {
                int sockfd = revs[i].data.fd;
                printf("n: %d,sockfd: %d\n",n,sockfd);
                uint32_t event = revs[i].events;
                if (event & EPOLLERR) // 有错误事件就绪
                    event |= (EPOLLIN | EPOLLOUT);
                if (event & EPOLLHUP) // 连接挂起或者断开
                {
                    lg(INFO,"Connect was break");
                    _ConnPool[sockfd]->_Except(_ConnPool[sockfd]);
                }
                if (ConnectIsExist(sockfd) && (event & EPOLLIN)) // 读事件就绪
                {
                    _ConnPool[sockfd]->_Read(_ConnPool[sockfd]);
                }
                if (ConnectIsExist(sockfd) && (event & EPOLLOUT)) // 写事件就绪
                {
                    _ConnPool[sockfd]->_Write(_ConnPool[sockfd]);
                }
            }
        }
    }
    void DelConnect(int sockfd)
    {
        epoll.Del(sockfd);
        close(sockfd);
        delete _ConnPool[sockfd]; 
        _ConnPool.erase(sockfd);
        lg(INFO,"sockfd: %d,brief success",sockfd);
    }
    void Dispatcher()
    {
        _isrunning = true;
        while(_isrunning)
        {
            LoopOnce();
        }
    }
    bool ConnectIsExist(int sockfd)
    {
        return _ConnPool.find(sockfd) != _ConnPool.end();
    }
    void PrintDebug()
    {
        for(auto& e:_ConnPool)
        {
            printf("list:%d,type: %d",e.first,e.second->_type);
        }
        printf("\n");
    }
private:
    std::unordered_map<int, class Connect*> _ConnPool;
    handlers _listen_sockfd_read = 0;
    handlers _normal_sockfd_read = 0;
    handlers _normal_sockfd_write = 0;
    handlers _except = 0;
    class Epoll epoll;
    struct epoll_event revs[MAXSIZE];
    bool _isrunning;
};

#endif